-
Notifications
You must be signed in to change notification settings - Fork 0
feat: #44 deploy the server build to where crate-api runs it #45
Conversation
|
Looks good overall! Just two small things before merging: Could you update the branch with the latest Also, the GraphQL smoke tests currently seem to check HTTP status codes only. Since GraphQL can return 200 even when the response contains errors, could we also check for an |
e9249e0 to
57db426
Compare
|
Both fixed, and the second one was demonstrable immediately. Branch updated. Rebased onto Smoke tests read the body now. You were right that a status check proves nothing. Here is the API currently running on the VM answering The old check printed Worth noting this will bite again when #42 lands, since a resolver that throws also returns 200 with an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took another look at the workflow after #42 was merged and noticed a couple of things:
- The
searchAlbumssmoke test is missing the requiredsortfield (AlbumSort!), so the query will fail validation. Addingsort: TITLE_ASCshould fix it. - Now that #42 is merged, should we make the workflow fail instead of skipping API deployment when
crate-api.serviceorserver/is missing? Otherwise the deployment job could pass without actually deploying the API.
The smoke tests could also be a bit more robust by validating the JSON response and checking the expected data, rather than just looking for "errors", but I think that's less urgent.
Could you also confirm that the systemd service loads DATABASE_URL from the root .env?
57db426 to
473e4bf
Compare
…checks Four points from rachelks on #45. 1. The searchAlbums smoke query omitted `sort`, which is `AlbumSort!` in AlbumSearchInput, so the query failed validation and the check could never pass. Now sends `sort: TITLE_ASC`. 2. The skip guards for crate-api.service and server/ now fail instead of exiting 0. #42 has merged so both are expected, and a deploy job that goes green without deploying anything is the wrong failure mode. 3. The body check parses the JSON rather than grepping for the word "errors". Grep would also fire on an album called "Errors", and it did not verify `data` was present at all. Now rejects a response with errors, with no data, or that is not JSON. Added a totalCount assertion as well, so the check is on the data and not only on its presence. 4. The python validators live in shell variables on one line. A multi-line `python3 -c` heredoc cannot be used inside a YAML block scalar: the block ends at the first unindented line and the workflow stops parsing. Learned by breaking it. Also rebased onto main now that #42 and #43 have merged. Validated the two python expressions against five payloads: a good response, GraphQL errors, null data, a valid totalCount, and two bad ones. Each rejected case prints what was wrong. Co-Authored-By: opencode <noreply@opencode.ai>
|
All four, and the first one was a real bug that meant the check could never have passed. 1. 2. Skip guards now fail. You are right that a deploy job going green without deploying is the wrong failure mode, and #42 has merged so both conditions are expected to hold. 3. The body check parses JSON now. Grep for the word Tested the two validators against five payloads: a good response, GraphQL errors, 4. Two things I had to fix along the way, in case they come up again: a multi-line |
README was still describing M1, and one line was simply wrong: it said `client/` renders mock data. The mock-data search interface never landed, the client is still the skeleton and #9 wires it straight to GraphQL. - Current milestone moved to M2 - New "Where the code is" table, implemented vs. planned - Local setup for `server/` too: DATABASE_URL, migrate, optional seed - Server commands in the command table - Infrastructure names `crate-api.service` and what CI deploys - M1 row now lists what M1 actually delivered, not mock data that did not land - Sort modes corrected to four, checked against `AlbumSort` in the schema AI usage log gets the eight erikhfj rows missing since 1 October: the #10 identity contract, the #8 VM runbook and the git clone, the #13 facet trade-off, the #43 source-map-js override, the #44 deploy gap, the displayName correction, the #45 review fixes, and this pass. The displayName row is the kind the log intro calls out as most important: the tool drafted a claim that a person had to correct. Per #48 each member documents their own usage, so only erikhfj rows were added. robertky's row from #46 was out of date order at the end of the table and is now with the rest of 9 October, and his relative order within the day is unchanged. Co-Authored-By: opencode <noreply@opencode.ai>
The workflow built server/ in the runner's own workspace and restarted crate-api, but nothing ever put that build where the unit actually runs it. crate-api.service has WorkingDirectory=~/T19-Project-2/server and ExecStart=.../node dist/index.js, so a restart just brought back whatever had been installed on the machine by hand. Reported by rachelks on #42. The deploy step now: 1. checks out $GITHUB_SHA in ~/T19-Project-2, which is a git clone of main as of this issue rather than a hand copy 2. installs and builds server/ there 3. restarts crate-api and polls until /graphql answers 4. runs a smoke suite through the same Apache proxy the browser uses Three things this fixes that were wrong before: - The unit check is [ -f ... ], not `systemctl list-unit-files | grep`. grep -q closes the pipe at the first match, systemctl dies of SIGPIPE, and with pipefail the pipeline reports failure. The if took the else branch and skipped a service that was definitely there. - The restart needs a NOPASSWD sudoers rule, because the runner has no TTY. Scoped to three systemctl commands. - No sleep. Type=simple reports active before Node binds the port, and a measured 1850 ms startup made `sleep 2` produce a 503 through Apache. It polls instead. Verified on the VM: ~/T19-Project-2 is a real clone at 0fbd54a, git fetch works with the deploy key added for that machine, `checkout --force` leaves .gitignore's .env untouched (it holds DATABASE_URL), and sudo is passwordless for the three commands. The skip guard for `server/` stays, because #42 has not merged yet. Once it does, the next push to main will deploy the API end to end. Co-Authored-By: opencode <noreply@opencode.ai>
rachelks: GraphQL returns HTTP 200 even when the payload carries errors,
so a status check proves nothing. She is right and it was demonstrable
immediately: querying searchAlbums against the API currently running on
the VM returns 200 with
{"errors":[{"message":"Unknown argument \"input\" on field
\"Query.searchAlbums\".","extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}]}
and the old check reported 200 and moved on.
The smoke suite now POSTs, splits the status line off the body, and
rejects the response if it is not 200 or if the body contains an "errors"
key. Verified against the live API: __typename passes, searchAlbums is
correctly rejected.
Branch also rebased onto main so it carries the source-map-js fix from
#43.
Reported by rachelks.
Co-Authored-By: opencode <noreply@opencode.ai>
…checks Four points from rachelks on #45. 1. The searchAlbums smoke query omitted `sort`, which is `AlbumSort!` in AlbumSearchInput, so the query failed validation and the check could never pass. Now sends `sort: TITLE_ASC`. 2. The skip guards for crate-api.service and server/ now fail instead of exiting 0. #42 has merged so both are expected, and a deploy job that goes green without deploying anything is the wrong failure mode. 3. The body check parses the JSON rather than grepping for the word "errors". Grep would also fire on an album called "Errors", and it did not verify `data` was present at all. Now rejects a response with errors, with no data, or that is not JSON. Added a totalCount assertion as well, so the check is on the data and not only on its presence. 4. The python validators live in shell variables on one line. A multi-line `python3 -c` heredoc cannot be used inside a YAML block scalar: the block ends at the first unindented line and the workflow stops parsing. Learned by breaking it. Also rebased onto main now that #42 and #43 have merged. Validated the two python expressions against five payloads: a good response, GraphQL errors, null data, a valid totalCount, and two bad ones. Each rejected case prints what was wrong. Co-Authored-By: opencode <noreply@opencode.ai>
#46 landed migration 0001 for tracks, simulated users, reviews and crate items, and pointed out that this deploy never runs db:migrate. It was right. A deploy that lands new migration files and does not apply them is the same gap as #44 one layer down: the code is current, the schema is not. Migrate runs before the restart, so the new build is never pointed at an old database. It runs on every deploy because db:migrate is idempotent (verified on #46), not only when the migration list changes. DATABASE_URL is exported from the same .env the systemd unit loads. The server package scripts look for `server/.env` instead, which may not exist in the deploy root, so it is passed explicitly rather than assuming the two agree. Node's --env-file does not override a variable already in the environment, so this wins even when server/.env is present. Verified that a URL-encoded password survives the sed extraction and the handoff to the child process byte for byte. Also rebased onto main, which brings #46 along. Co-Authored-By: opencode <noreply@opencode.ai>
473e4bf to
4c1ab0d
Compare
|
One more change, and this one is not from review but from #46 merging. #46 landed migration
Two details worth knowing: Where A password with a URL-encoded character survives the handoff. Checked Branch is rebased onto |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good now! The migration step is in place and I couldn't find any remaining blocking issues. Thanks for fixing this!
Why
rachelks on #42: "workflowen bygger den nye serveren, og restarter crate-api.service, men fant ikke noe steg som deployer selve backend-builden".
She is right.
crate-api.servicerunsnode dist/index.jsfrom~/T19-Project-2/server. The workflow builtserver/in the runner's own workspace,_work/T19-Project-2/T19-Project-2, and never copied that build anywhere. Restarting the unit just brought back whatever process had been installed on the machine by hand, which is still an early prototype from 23 September.What this does
The deploy step now goes through
~/T19-Project-2, which is a git clone ofmainas of this issue:git checkout --force $GITHUB_SHAtherepnpm installand buildserver/systemctl restart crate-api, poll until/graphqlanswersChecking out the tested SHA rather than rsyncing files means what runs is exactly what CI built.
The VM work behind it
~/T19-Project-2was a hand copy with no.git. Replacing it needed git access from the machine, which it did not have:~/.ssh/id_ed25519_giton the VMgh api user/keys, id 3852)ssh-keyscanfor the host key and an~/.ssh/configentry so git picks the key upmain, restored.env.envis in.gitignore, sogit checkout --forceleaves it alone. Verified: same md5 before and after.Three bugs from earlier that this does not repeat
grep -q+pipefailsystemctldied of SIGPIPE, and theiftook the else branch and skipped a service that was there. Now[ -f /etc/systemd/system/crate-api.service ].sudowith no TTYsystemctlcommands, already installed on the VM.sleep 2before the health checkType=simplereports active before Node binds the port. Measured 1878 / 1850 / 1864 ms, sosleep 2left 120 ms of margin and/graphqlreturned 503 through Apache. Now polls.What was tested
Against the live VM:
~/T19-Project-2/.gitexists0fbd54agit fetch originwith the deploy keygit checkout --force HEADkeeps.envserver/is absentsudo -n systemctl is-active crate-apiactive, no promptPOST /graphql,GET /project2/Also
pnpm format:check,pnpm lint,pnpm typecheckandpnpm testall pass.What still waits on #42
server/is not onmainyet, so the step's skip guard is what runs today. Once #42 merges, the next push tomaindeploys the API end to end and the smoke suite runs for real. That is the last acceptance line of #44:I cannot verify that until there is a server to run.
Closes
Implements #44. The reboot acceptance line closes when #42 has landed and a deploy has run against it.